#include "photo.h"
extern struct input_event key_value;

extern volatile int is_enter; //标记是否打开程序
extern volatile int is_open; //标记是否打开图片
extern volatile int page_sum; //标记总页数
extern volatile int page; //标记当前页号，从1开始
extern volatile int choice; //标记选中哪一张图片(0-1-2-3)

extern int photo_sum;


extern FILE *bmp[PICNUM];
extern FILE *bmp_exit;
extern FILE *bmp_start;
extern int *fb_mem;
extern char buff[WIDTH * HEIGHT * 3];

extern pid_t pptpid;
extern int pptfd[2]; //管道，pptfd[0]是读端，pptfd[1]是写端。

void config_var()
{
	is_enter = 0; //标记是否打开程序
	is_open = 0; //标记是否打开图片
	page_sum = 0; //标记总页数
	page = 1; //标记当前页号，从1开始
	choice = 0; //标记选中哪一张图片(0-1-2-3)

	/*
	 *计算出相册的页数page_sum
	 */
	if ((PICNUM % 4) == 0) {
		page_sum = PICNUM / 4;
	} else {
		page_sum = PICNUM / 4 + 1;
	}

	printf("page_sum:%d\n", page_sum);

	bmp_start = fopen(BEGIN, "r"); //进入的界面
	bmp_exit = fopen(END, "r"); //退出的界面

	DIR *dir = opendir(PICDIR);
	if (dir != NULL) {
		get_file(dir);
		draw_lcd(bmp_start, 0, WIDTH - 1, 0, HEIGHT - 1, 0, 0);
		kill(DAEMON, BEGINS); //开启
	}
}

void draw_lcd(FILE *bmps, int x1, int x2, int y1, int y2, int z1, int z2)
{ //按给定参数绘制图片
	/* x1:x起始位置;  x2:x结束位置;  y1:y起始位置;  y2:y结束位置;  z1:行偏移位置;  z2:列偏移位置 
	 * 函数作用：从(x1, y1)到(x2, y2)绘制图片bmps 
	 * 横向每(z1 + 1)个像素并为一个，纵向每(z2 + 1)行并为一行, z1、z2需配合x1、x2、y1和y2 */
	int x = 0;
	int y = 0;
	int i = 0;
	fseek(bmps, 54, SEEK_SET);
	fread(buff, WIDTH * HEIGHT * 3, 1, bmps);
	for (y = y2; y >= y1; y--) {
		for (x = x1; x <= x2; x++) {
			*(fb_mem + y * WIDTH + x) = (buff[i] << 0 | buff[i + 1] << 8 | buff[i + 2] << 16);
			i += 3 * (z1 + 1);
		}
		i += z2 * WIDTH * 3;
	}
}

void to_page()
{ //按页号将四张图片输出为一张
	if (((page - 1) * 4) > PICNUM || page <= 0) { //超出图库范围则报错
		perror("Page Out Of Range\n");
		printf("page:%d\n", page);
		return;
	} else {
		printf("page:%d\n", page);
		//Read((0,0)~(399,239))
		draw_lcd(bmp[4 * (page - 1)], 0, WIDTH / 2 - 1, 0, HEIGHT / 2 - 1, 1, 1); //(0, 0) -> (WIDTH / 2 - 1, HEIGHT / 2 - 1), 偏移像素1，偏移行数1

		//Read((400,0)~(799,239))
		if ((4 * (page - 1) + 1) < PICNUM) {
			draw_lcd(bmp[4 * (page - 1) + 1], WIDTH / 2, WIDTH - 1, 0, HEIGHT / 2 - 1, 1, 1); //(WIDTH / 2, 0) -> (WIDTH - 1, HEIGHT / 2 - 1), 偏移像素1，偏移行数1
		} else {//画空白的页
			int x = 0;
			int y = 0;
			for (y = (HEIGHT / 2 - 1); y >= 0; y--) {
				for (x = WIDTH / 2; x < WIDTH; x++) {
					*(fb_mem + y * WIDTH + x) = 0xb5b5b5;
				}
			}
		}
		//Read((0,240)~(399,479))
		if ((4 * (page - 1) + 2) < PICNUM) {
			draw_lcd(bmp[4 * (page - 1) + 2], 0, WIDTH / 2 - 1, HEIGHT / 2, HEIGHT - 1, 1, 1);
		} else {//画空白的页
			int x = 0;
			int y = 0;
			for (y = (HEIGHT - 1); y >= (HEIGHT / 2); y--) {
				for (x = 0; x < WIDTH / 2; x++) {
					*(fb_mem + y * WIDTH + x) = 0xaaaaaa;
				}
			}
		}
		//Read((400,479)~(799,239))
		if ((4 * (page - 1) + 3) < PICNUM) {
			draw_lcd(bmp[4 * (page - 1) + 3], WIDTH / 2, WIDTH - 1, HEIGHT / 2, HEIGHT - 1, 1, 1);
		} else {
			int x = 0;
			int y = 0;
			for (y = (HEIGHT - 1); y >= (HEIGHT / 2); y--) {
				for (x = WIDTH / 2; x < WIDTH; x++) {
					*(fb_mem + y * WIDTH + x) = 0x969696;
				}
			}
		}
	}
}

void draw_frame()
{ //为选中的图片绘制红框
	if (choice >= 0 && choice <= 3) {
		printf("choice:%d\n", choice);
		int i = 0;
		int offL = choice % 2;
		int offH = choice / 2;
		to_page();
		for (i = (WIDTH / 2) * offL; i < (WIDTH / 2) * (offL + 1); i++) {
			//四条横线
			*(fb_mem + ((HEIGHT / 2) * offH) * WIDTH + i) = 0xff0000;
			*(fb_mem + ((HEIGHT / 2) * offH + 1) * WIDTH + i) = 0xff0000;
			*(fb_mem + ((HEIGHT / 2) * (offH + 1) - 2) * WIDTH + i) = 0xff0000;
			*(fb_mem + ((HEIGHT / 2) * (offH + 1) - 1) * WIDTH + i) = 0xff0000;
		}
		for (i = (HEIGHT / 2) * offH + 2; i < ((HEIGHT / 2) * (offH + 1) - 2); i++) {
			//四条竖线
			*(fb_mem + i * WIDTH + (WIDTH / 2) * offL) = 0xff0000;
			*(fb_mem + i * WIDTH + (WIDTH / 2) * offL + 1) = 0xff0000;
			*(fb_mem + i * WIDTH + (WIDTH / 2) * (offL + 1) - 1) = 0xff0000;
			*(fb_mem + i * WIDTH + (WIDTH / 2) * (offL + 1) - 2) = 0xff0000;
		}
	}
}

void get_file(DIR *dir)
{ //读取图片文件
	if (dir != NULL && bmp != NULL) {
		int i = 0;
		if (dir != NULL) {
			struct dirent *d_p;
			while ((d_p = readdir(dir)) != NULL && i < PICNUM) {

				if (strstr(d_p->d_name, ".bmp")) {
					char *path = (char *) malloc(sizeof(char)*255);
					memset(path, 0, sizeof(255));
					strncat(path, PICDIR, strlen(PICDIR));
					printf("strlen(PICDIR):%d  line:%d\n", strlen(PICDIR), __LINE__);
					strncat(path, d_p->d_name, strlen(d_p->d_name));
					printf("name:%s\n", path);
					bmp[i] = fopen(path, "r");
					if (bmp[i] == NULL) {
						perror("Read Pic Failed!\n");
						_exit(0);
					}
					i++;
				}
			}
		}
	}
}

void key_back()
{ //返回小图模式
	if (is_enter == 1 && is_open == 1) {
		kill(pptpid, SIGINT);
		to_page();
		draw_frame();
		is_open = 0;
	}
}

void key_enter()
{ //进入主程序
	if (is_enter == 0) {
		//Enter
		to_page();
		draw_frame();
		is_enter = 1;
	}
}

void key_exit()
{ //退出程序
	draw_lcd(bmp_exit, 0, WIDTH - 1, 0, HEIGHT - 1, 0, 0);
	kill(pptpid, SIGINT);
	kill(DAEMON, QUITS);
	is_enter = 0;
	sleep(3);
}

void getNext(int sig)
{
	if (sig == RETURN) {
		char buff[2];
		read(pptfd[0], buff, 2);
		page = buff[0];
		choice = buff[1];
	}
}

void pptQuit(int sig)
{
	if (sig == SIGINT) {
		char buff[2];
		buff[0] = page;
		buff[1] = choice;
		write(pptfd[1], buff, 2);
		kill(getppid(), RETURN);
		close_pic();
		exit(0);
	}
}

void *Thread(void *p)
{
	int arg = (int) p;
	int num = arg / 10;
	int method = arg % 10;
	int x = 0;
	int y = 0;
	int pos = (3 - num) * (HEIGHT / 4) * 3 * WIDTH;
	if (method == 0) { //下向上
		for (y = (num + 1) * (HEIGHT / 4) - 1; y >= num * (HEIGHT / 4); y--) {
			for (x = 0; x <= WIDTH - 1; x++) {
				*(fb_mem + y * WIDTH + x) = (buff[pos] << 0 | buff[pos + 1] << 8 | buff[pos + 2] << 16);
				pos += 3;
			}
			usleep(8000);
		}
	} else if (method == 1) { //左向右
		for (x = num * (WIDTH / 4); x <= (num + 1) * (WIDTH / 4) - 1; x++) {
			pos = 3 * x;
			for (y = HEIGHT - 1; y >= 0; y--) {
				*(fb_mem + y * WIDTH + x) = (buff[pos] << 0 | buff[pos + 1] << 8 | buff[pos + 2] << 16);
				pos += 3 * WIDTH;
			}
			usleep(8000);
		}
	} else if (method == 2) {//上向下
		pos = ((4 - num) * (HEIGHT / 4) - 1) * 3 * WIDTH; //偏移到每块的顶行
		for (y = num * (HEIGHT / 4); y <= (num + 1) * (HEIGHT / 4) - 1; y++) {
			for (x = 0; x <= WIDTH - 1; x++) {
				*(fb_mem + y * WIDTH + x) = (buff[pos] << 0 | buff[pos + 1] << 8 | buff[pos + 2] << 16); //扫描并显示一行
				pos += 3;
			}
			pos = pos - 6 * WIDTH; //回退两行，即刷新刚才一行的下边一行
			//不回退的话就会显示刚才一行的上一行
			usleep(8000);
		}
	} else if (method == 3) { //右向左
		for (x = (num + 1) * (WIDTH / 4) - 1; x >= num * (WIDTH / 4); x--) {
			pos = 3 * x;
			for (y = HEIGHT - 1; y >= 0; y--) {
				*(fb_mem + y * WIDTH + x) = (buff[pos] << 0 | buff[pos + 1] << 8 | buff[pos + 2] << 16);
				pos += 3 * WIDTH;
			}
			usleep(8000);
		}
	}
	pthread_exit(NULL);
}

void DrawInWindows(FILE *bmps, int method)
{
	fseek(bmps, 54, SEEK_SET);
	fread(buff, WIDTH * HEIGHT * 3, 1, bmps);
	method = method % 10;
	//  method = 3;
	pthread_t pth[THNUM];
	int i = 0;
	for (i = 0; i < THNUM; i++) {
		pthread_create(&pth[i], NULL, Thread, (void *) (i * 10 + method));
	}
	for (i = 0; i < THNUM; i++) {
		pthread_join(pth[i], NULL);
	}
}

void key_open()
{ //打开选中的图片
	printf("open\n");
	if (is_enter == 1 && is_open == 0 && choice >= 0 && choice <= 3) {
		//OPEN
		int method = 0;
		DrawInWindows(bmp[4 * (page - 1) + choice], method);
		pipe(pptfd); //创建了管道，
		pptpid = fork();
		if (pptpid == 0) {
			close(pptfd[0]);
			signal(SIGINT, pptQuit);
			int current = 4 * (page - 1) + choice;
			while (1) {
				method = (method + 1) % 4;
				sleep(3);
				current = (current + 1) % PICNUM;
				page = current / 4 + 1;
				choice = current % 4;
				DrawInWindows(bmp[current], method);
			}
		} else if (pptpid != 0) {
			close(pptfd[1]);
			is_open = 1;
			signal(RETURN, getNext);
		}
	}
}

void key_page_up()
{ //上一页
	printf("KEY page up\n");
	if (is_enter == 1 && is_open == 0) {
		if (page <= 1) { //已是第一页
			page = page_sum; //跳到最后一页
		} else {
			page--;
		}
		//回到最后一页的最后一张。如果choice是满页中的第四张图片，则上翻到最后一张会越界。
		while (4 * (page - 1) + choice >= PICNUM) {
			choice--;
		}
		to_page();
		draw_frame();
	}
}

void key_page_down()
{ //下一页
	printf("KEY page down\n");
	if (is_enter == 1 && is_open == 0) {
		if (page >= page_sum) {
			page = 1;
		} else {
			page++;
		}
		//翻到最后一页的最后一张。如果choice是满页中的第四张图片，则下翻到最后一张会越界。
		while (4 * (page - 1) + choice >= PICNUM) {
			choice--;
		}
		to_page();
		draw_frame();
	}
}

void key_up()
{ //上一张
	printf("KEY up\n");
	if (is_enter == 1 && is_open == 0) {
		char flag = 'n';
		if (choice <= 0) {
			choice = 3;
			flag = 'y';
		} else {
			choice--;
			flag = 'y';
		}
		while (4 * (page - 1) + choice >= PICNUM) {
			choice--;
			flag = 'n';
		}
		if (flag == 'y') {
			kill(DAEMON, UPS);
			draw_frame();
		}
	}
}

void key_down()
{ //下一张
	printf("KEY down\n");
	if (is_enter == 1 && is_open == 0 && 4 * (page - 1) + choice < PICNUM) {
		char flag = 'n';
		if (choice >= 3) {
			choice = 0;
			flag = 'y';
		} else {
			choice++;
			flag = 'y';
		}
		while (4 * (page - 1) + choice >= PICNUM) {
			choice--;
			flag = 'n';
		}
		if (flag == 'y') {
			kill(DAEMON, DOWNS);
			draw_frame();
		}
	}
}

void close_pic()
{
	int i = 0;
	for (; i++; i < PICNUM) {
		if (bmp[i] != NULL) {
			fclose(bmp[i]);
		}
	}
	return;
}

void pic_effect(int code)
{

	switch (code) {
	case ESC:
	{ //返回小图模式
		key_back();
		break;
	}
	case HOME:
	{ //进入主程序
		key_enter();
		break;
	}
	case POWER:
	{ //退出程序
		key_exit();
		break;
	}
	case ENTER:
	{ //打开选中的图片
		key_open();
		break;
	}
	case UP:
	{ //上一页
		key_page_up();
		break;
	}
	case DOWN:
	{ //下一页
		key_page_down();
		break;
	}
	case LEFT:
	{ //上一张图片
		key_up();
		break;
	}
	case RIGHT:
	{ //下一张图片
		key_down();
		break;
	}
	default:
	{
		perror("no such KEY !\n");
	}
	}
}